package com.ljx.itbbs.server.article.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.ljx.itbbs.common.domain.entity.UserEntity;
import com.ljx.itbbs.common.domain.vo.resp.CursorResp;
import com.ljx.itbbs.common.exception.BusinessException;
import com.ljx.itbbs.common.utils.AssertUtil;
import com.ljx.itbbs.common.utils.RedisUtil;
import com.ljx.itbbs.server.article.dao.CommentDao;
import com.ljx.itbbs.server.article.domain.entity.CommentEntity;
import com.ljx.itbbs.server.article.domain.entity.LikeRecordEntity;
import com.ljx.itbbs.server.article.domain.enums.CommentLikeEnum;
import com.ljx.itbbs.server.article.domain.enums.LikeEnum;
import com.ljx.itbbs.server.article.domain.vo.req.ArticleCommentReq;
import com.ljx.itbbs.server.article.domain.vo.req.CommentSaveReq;
import com.ljx.itbbs.server.article.domain.vo.resp.CommentResp;
import com.ljx.itbbs.server.article.event.CommentPostEvent;
import com.ljx.itbbs.server.article.event.DislikeEvent;
import com.ljx.itbbs.server.article.event.LikeEvent;
import com.ljx.itbbs.server.article.service.CommentReplyService;
import com.ljx.itbbs.server.article.service.CommentService;
import com.ljx.itbbs.server.article.service.LikeRecordService;
import com.ljx.itbbs.server.article.service.SensitiveService;
import com.ljx.itbbs.server.article.service.adapter.CommentAdapter;
import com.ljx.itbbs.server.article.service.cache.CommentCache;
import com.ljx.itbbs.server.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CommentDao commentDao;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private UserService userService;

    @Autowired
    private CommentCache commentCache;

    @Autowired
    private CommentReplyService commentReplyService;

    @Autowired
    private LikeRecordService likeRecordService;

    @Autowired
    private SensitiveService sensitiveService;

    @Override
    @Transactional
    public void postComment(Long userId, CommentSaveReq req) {
        // 检验评论敏感词
        sensitiveService.checkSensitive(req.getContent());
        if (Objects.isNull(req.getCommentId())){
            // 保存评论
            CommentEntity commentEntity = CommentAdapter.buildCommentSave(userId, req);
            commentDao.save(commentEntity);
        } else {
            // 保存回复
            commentReplyService.saveCommentReply(CommentAdapter.buildCommentReplySave(userId, req));
        }
        // 如果有回复ID，就增加父ID的回复量；递增文章浏览量
        applicationEventPublisher.publishEvent(new CommentPostEvent(this, req.getCommentId(), req.getArticleId()));

    }

    @Override
    public void increaseReplyNum(Long id) {
        commentDao.increaseReplyNum(id);
    }

    @Override
    public CursorResp<CommentResp> getArticleComment(ArticleCommentReq req) {
        CursorResp<CommentEntity> page = commentDao.getCommentList(req);
        List<CommentEntity> commentList = page.getList();
        List<Long> uIds = commentList.stream().map(CommentEntity::getUid).collect(Collectors.toList());
        Map<Long, UserEntity> userMap = userService.getUserInfoByIds(uIds);
        List<CommentResp> records = commentList.stream().map(item -> {
            CommentResp commentResp = BeanUtil.copyProperties(item, CommentResp.class);
            return setUserInfo(item, userMap, commentResp);
        }).collect(Collectors.toList());

        return CursorResp.<CommentResp>builder()
                .list(records)
                .isLast(page.isLast())
                .cursor(page.getCursor())
                .build();

    }

    private CommentResp setUserInfo(CommentEntity item, Map<Long, UserEntity> userMap, CommentResp commentResp) {
        UserEntity user = userMap.get(item.getUid());
        commentResp.setNickname(user.getNickname());
        commentResp.setAvatar(user.getAvatar());
        commentResp.setGrade(user.getGrade());

        return commentResp;
    }

    @Override
    public List<CommentResp> getNewComment() {
        List<CommentEntity> newComment = commentDao.getNewComment();
        List<Long> uIds = newComment.stream().map(CommentEntity::getUid).collect(Collectors.toList());
        Map<Long, UserEntity> userMap = userService.getUserInfoByIds(uIds);

        return newComment.stream().map(item -> {
            CommentResp commentResp = BeanUtil.copyProperties(item, CommentResp.class);
            return setUserInfo(item, userMap, commentResp);
        }).collect(Collectors.toList());
    }

    @Override
    public void likeComment(Long userId, Long commentId, Integer commentType) {
        // 查询是否已经点赞过了
        String key = LikeEnum.getObjKey(LikeEnum.COMMENT, commentType + ":" + commentId.toString());
        LikeRecordEntity likeRecord = likeRecordService.getLikeRecord(key, userId);
        if (Objects.nonNull(likeRecord)){
            // 取消点赞和删除记录
            applicationEventPublisher.publishEvent(
                    new DislikeEvent(this, likeRecord.getUserId(), likeRecord.getLikeObj(), likeRecord.getType(),
                            commentId, commentType)
            );
            throw new BusinessException("取消点赞");
        }

        applicationEventPublisher.publishEvent(
                new LikeEvent(this, key, userId, commentId, LikeEnum.COMMENT.getType(), commentType));
    }

    @Override
    public void increaseLikeNum(Long objId, Integer commentType) {
        if (commentType.equals(CommentLikeEnum.P_COMMENT.getType())){
            // 点赞父评论
            commentDao.likeComment(objId);
        } else {
            // 点赞子评论
            commentReplyService.likeCommentReply(objId);
        }
    }

    @Override
    public void reduceLikeNum(Long objId, Integer commentType) {
        if (commentType.equals(CommentLikeEnum.P_COMMENT.getType())){
            // 取消点赞父评论
            commentDao.reduceCommentLikeNum(objId);
        } else {
            // 取消点赞子评论
            commentReplyService.reduceCommentReplyLikeNum(objId);
        }
    }
}
